package org.mwielocha.jxcube.player;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashSet;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.text.Position;

public class MPlayerFrontend implements IPlayer, Runnable {
  
  protected Process mplayerProcess;
  
  protected Executor executor;
  
  protected ResourceBundle config;
  
  protected Set<IPlayerListener> listeners;
  
  protected boolean close;
  
  public MPlayerFrontend() {
    executor = Executors.newFixedThreadPool(1);
    listeners = new HashSet<IPlayerListener>();
    config = ResourceBundle.getBundle("properties/config");
  }
  
  public void init() throws IOException {
    executor.execute(this);
  }
  
  @Override
  public void run() {
    try {
      mplayerProcess = Runtime.getRuntime().
        exec(config.getString("mplayer.executable") + " -ao " + config.getString("mplayer.output") + " -idle -slave");
      while(true) {
        BufferedReader r = new BufferedReader(new InputStreamReader(mplayerProcess.getInputStream()));
        String all = "";
        String line = "";
        while((line = r.readLine()) != null && !close) {
       //   System.out.println(line);
          
          Pattern p = Pattern.compile(".: *(\\d*):?(\\d*).(\\d).*");
          Matcher m = p.matcher(line);
          
          if (m.matches()) {
            parseFeedback(line);
          }
          
          
        }
        r.close();
        System.out.println(all);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  @Override
  public void setVolume(int value) throws IOException {
    send("volume " + value + " 1\n");
    fireVolumeChangeEvent(value);
  }
  
  public void play(String path) throws IOException {
    System.out.println(path);
    String command = "loadfile \"" + path.replace("\\", "/") + "\" 0 \n";
    send(command);
    
  }
  
  @Override
  public void enque(String path) throws IOException {
    send("loadfile " + path.replace(" ", "\\ ") + " 1 \n");
  }
  
  @Override
  public void stop() throws IOException {
    send("seek 0 1 \n");
    send("pause \n");
  }
  
  protected void send(String command) throws IOException {
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(mplayerProcess.getOutputStream()));
    bw.write(command);
    bw.flush();
  }
  
  public void close() throws IOException {
    close = true;
    send("quit \n");
  }
  
  @Override
  public void setPosition(double position) throws IOException {
    send("mute \n");
    send("seek " + position + " 2 \n");
    send("mute \n");
  }
  
  public void addPlayerListener(IPlayerListener l) {
    listeners.add(l);
  }
  
  public void removePlayerListener(IPlayerListener l) {
    listeners.remove(l);
  }
  
  protected void parseFeedback(String feedback) {
    feedback = feedback.replace("A:", "");
    int idx = feedback.lastIndexOf(")");
    feedback = feedback.substring(0, idx + 1);
  //  System.out.println("feedback: " + feedback);
    String[] split = feedback.split("of");
  //  System.out.println(split[0]);
  //  System.out.println(split[1]);
    
    try {
    
      String currentTime = split[0].replace(")", "");
      currentTime = currentTime.replace("(", "-");
   //   System.out.println(currentTime);
      String[] currentTimeArray = currentTime.trim().split("-");
      double currentPosition = Double.parseDouble(currentTimeArray[0]);
 //     System.out.println("currentPosition: " + currentPosition);
      
      String totalTime = split[1].replace(")", "");
      currentTime = totalTime.replace("(", "-");
    //  System.out.println(totalTime);
      String[] totalTimeArray = currentTime.trim().split("-");
      double lastPosition = Double.parseDouble(totalTimeArray[0]);
  //    System.out.println("lastPosition: " + lastPosition);
      
      if(currentPosition == (lastPosition - 1)) {
        fireTrackFinishedEvent();
      } else {
        firePositionChangeEvent(currentPosition, lastPosition);
      }
    } catch (NumberFormatException e) {
      e.printStackTrace();
    }
  }
  
  protected void firePositionChangeEvent(double position, double lastPosition) {
    for(IPlayerListener l : listeners) {
      l.positionChangeEvent(position, lastPosition);
    }
  }
  
  protected void fireStarEvent() {
    for(IPlayerListener l : listeners) {
      l.playEvent();
    }
  }
  
  protected void fireStopListener() {
    for(IPlayerListener l : listeners) {
      l.stopEvent();
    }
  }
  
  protected void fireTrackFinishedEvent() {
    for(IPlayerListener l : listeners) {
      l.trackFinishedEvent();
    }
  }
  
  public void fireVolumeChangeEvent(int volume) {
    for(IPlayerListener l : listeners) {
      l.volumeChangedEvent(volume);
    }
  }
}
